#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:6031)

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stddef.h>

//内存操作函数
//memcpy - 内存拷贝

//void* my_memcpy(void* dest, const void* src, size_t num)
//{
//	assert(dest && src);
//
//	char* start = (char*)dest;
//	while (num--)
//	{
//		*start = *(char*)src;
//		start++;
//		src = (char*)src + 1;
//		//*start++ = *((char*)src)++;	//不推荐
//	}
//
//	return dest;
//}
//
//memcpy函数应该拷贝不重叠的内存
//memmove函数可以处理内存重叠的情况
//int main()
//{
//	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int arr2[10] = { 0 };
//
//	my_memcpy(arr2, arr1, 20);
//
//	return 0;
//}

//void* my_memmove(void* dest, const void* src, size_t num)
//{
//	char* start = (char*)dest;
//	assert(dest && src);
//	if (dest<src)
//	{
//		//从前向后拷贝
//		while (num--)
//		{
//			*start = *(char*)src;
//			start++;
//			src = (char*)src + 1;
//			
//		}
//	}
//	else
//	{
//		//从后向前拷贝
//		while (num--)
//		{
//			*(start + num) = *((char*)src + num);
//		}
//	}
//	return dest;
//}
//
//int main()
//{
//	int arr1[20] = { 1,2,3,4,5,6,7,8,9,10 };
//	//my_memmove(arr1 + 2, arr1, 20);
//	my_memmove(arr1, arr1 + 2, 20);
//
// 	return 0;
//}

//int main()
//{
//	float arr1[] = { 1.0, 2.0, 3.0, 4.0 };
//	float arr2[] = { 1.0, 3.0 };
//	int ret = memcmp(arr1, arr2, 8);
//	printf("%d\n", ret);
//
//	return 0;
//}

//int main()
//{
//	int arr[10] = { 0 };
//	memset(arr, 255, 20);//以字节为单位设置内存
//
//	return 0;
//}

//匿名结构体类型
//struct
//{
//	char c;
//	int i;
//} s;
//
//struct
//{
//	char c;
//	int i;
//}* ps;
//
//int main()
//{
//	ps = &s;	//warning
//
//	return 0;
//}

//结构体的自引用
//struct Node
//{
//	int data;	//数据域
//	struct Node* next;	//指针域
//};
//
//typedef struct Node
//{
//	int data;
//	struct Node* next;
//}Node;

//结构体内存对齐
//1.第一个成员在与结构体变量偏移量为0的地址处
//2.其它成员变量要对齐到某个数字（对齐数）的整数倍的地址处
//对齐数，编译器默认的一个对齐数与该成员大小的较小值
//3.结构体的总大小为所有成员的对齐数中最大值的整数倍
//4.嵌套结构体对齐到自己的最大对齐数的整数倍处，结构体的整体
//大小就是所有最大对齐数（含嵌套结构体的对齐数）的整数倍
//struct S
//{
//	char c1;
//	int i;
//	char c2;
//};
//
//struct S2
//{
//	char c1;
//	int i;
//	double d;
//};
//
//int main()
//{
//	struct S s = { 0 };
//	struct S2 s2 = { 0 };
//	printf("%d\n", sizeof(s));	//12
//	printf("%d\n", sizeof(s2));	//16
//	return 0;
//}
//设计结构体时，空间占用小的成员尽量集中在一起

//把默认对齐数改为2
//#pragma pack(2)
//struct S
//{
//	char c1;
//	int i;
//	char c2;
//};
//#pragma pack()
//
//int main()
//{
//	printf("%d", sizeof(struct S));
//	return 0;
//}

//struct S
//{
//	char c1;
//	int i;
//	char c2;
//};
//
//int main()
//{
//	printf("%d\n", offsetof(struct S, c1));
//	printf("%d\n", offsetof(struct S, i));
//	printf("%d\n", offsetof(struct S, c2));
//
//	return 0;
//}

//结构体传参，传地址 

//位段的声明和结构类似，但有两个不同：
//1.位段的成员必须是int、unsigned int或signed int。
//2.位段的成员名后边有一个冒号和一个数字

//位段的内存分配
//1.位段的成员可以是int、unsigned int、signed int或者是char(属于整型家族)类型
//2.位段的空间上是按照需要4个字节(int)或者1个字节(char)的方式来开辟的
//3.位段涉及很多不确定因素，位段是不跨平台的，注重可移植的程序应该避免使用位段
//struct A
//{
//	int _a : 2;	//_a 成员占2个bit位,最大32
//	int _b : 5;
//	int _c : 10;
//	int _d : 30;
//};
//
//int main()
//{
//	printf("%d\n", sizeof(struct A));
//}
//enum Color
//{
//	RED,
//	GREEN,
//	BLUE
//};
//
//int main()
//{
//	enum Color c = BLUE;
//	printf("%d\n", RED);
//	printf("%d\n", GREEN);
//	printf("%d\n", BLUE);
//
//	return 0;
//}

//union Un
//{
//	char c;
//	int i;
//};
//
//int main()
//{
//	union Un u = {10};
//	u.i = 1000;
//	u.c = 100;
//	printf("%p\n", &u);
//	printf("%p\n", &(u.c));
//	printf("%p\n", &(u.i));	//三个相同的地址
//
//	//printf("%d\n", sizeof(u));	//4
//
//	return 0;
//}

//int check_sys()
//{
//	union U
//	{
//		char c;
//		int i;
//	}u;
//	u.i = 1;
//	return u.c;
//}
//
//int main()
//{
//	if (check_sys() == 1)
//	{
//		printf("小端字节序");
//	}
//	else
//	{
//		printf("大端字节序");
//	}
//
//	return 0;
//}
// 
//联合体的大小至少是最大成员的大小
//当最大成员大小不是最大对齐数的整数倍时，需要与最大对齐数的整数倍对齐
//union Un
//{
//	char a[5];
//	int i;
//};
//
//int main()
//{
//	union Un u;
//	printf("%d\n", sizeof(u));	//8
//
//	return 0;
//}